<?php

require_once('Adept/Db/IConnection.php');

class Adept_Db_MySql_Connection implements Adept_Db_IConnection 
{ 
    
    protected $connectionId;
    protected $config;
    
    /**
     * @param Adept_Db_Config $config
     * @return Adept_Db_MySql_Connection
     */
    public function __construct($config) 
    {
        $this->config = $config;    
    }
    
    /**
     * Execute a SQL script and return result. Raise error if execution failed.
     * 
     * @param string $sql
     * @return mixed
     */
    public function execute($sql) 
    {
        $result = mysql_query($sql, $this->getConnectionId());
        if ($result == false) {
            throw new Adept_Db_Exception('SQL execution error. ', mysql_errno($this->getConnectionId()), 
            array(
                'message' => mysql_error($this->getConnectionId()),
                'sql' => $sql
            )
            );
        }
        return $result;
    }
    
    /**
     * Try to connect to database
     * @return bool Success flag
     */
    public function connect() 
    {
        $this->connectionId = mysql_connect(
            $this->config->getHost(), 
            $this->config->getUser(), 
            $this->config->getPassword());    
            
        if (!$this->connectionId) {
            $this->connectionId = null;
            throw new Adept_Db_Exception('DB connect fault', mysql_errno($this->getConnectionId()), 
            array(
                'message' => mysql_error(),
                'config' => $this->config->__toString(),
            )
            );
        }
        
        if (!mysql_select_db($this->config->getDatabase())) {
            throw new Adept_Db_Exception('DB select fault', mysql_errno($this->getConnectionId()), 
            array(
                'message' => mysql_error($this->getConnectionId()),
                'config' => $this->config->__toString(),
            )
            );
        }
        
        $charset = $this->config->getCharset();
        if ($charset) {
            if (!mysql_query("SET CHARSET '{$charset}' ", $this->connectionId)) {
            throw new Adept_Db_Exception('DB charset setup fault', mysql_errno($this->getConnectionId()), 
                array(
                'message' => mysql_error($this->getConnectionId()),
                'config' => $this->config,
                )
            );
            }
        }
        
        return true;
    }
    
    /**
     * Return connection descriptor
     * 
     * @return resource
     */
    function getConnectionId() 
    {
        return $this->connectionId;
    }
    
    /**
     * Return true if connection available, otherwise false
     * @return bool
     */
    public function isConnected() 
    {
        return isset($this->connectionId) && !is_null($this->connectionId);
    }
    
    /**
     * Break connection with DB
     */
    function disconnect() 
    {
        if ($this->isConntected()) {
            mysql_close($this->connectionId);
        }
    }
    
    /**
     * Create new statement object. Result can be instance of 
     * MySqlQueryStatement (for SELECT, SHOW, DESCRIBE, EXLAIN), 
     * MySqlInsertStatement (for INSERT), MySqlManipulationStatement (for DELETE, UPDATE)
     * and MySqlStatement in other cases.
     * 
     * @see Adept_Db_MySql_Statement
     *
     * @param string $sql Base SQL script
     * @param array $params
     * @return object Instance of statement object
     */
    public function newStatement($sql, $params = array()) 
    {
        if ($sql instanceof Adept_Db_Query_Abstract) {
            $sql = $sql->__toString();
        }
        
        if (preg_match('~^\s*\(*\s*(\w+).*$~m', $sql, $match)) {
            $statement = $match[1];
        } else {
            $statement = $sql;
        }
        
        switch(strtoupper($statement)) {
            case 'SELECT':
            case 'SHOW':
            case 'DESCRIBE':
            case 'EXPLAIN':
            return new Adept_Db_MySql_Statement_Query($this, $sql);
            case 'INSERT':
            return new Adept_Db_MySql_Statement_Insert($this, $sql);
            case 'UPDATE':
            case 'DELETE':
            return new Adept_Db_MySql_Statement_Manipulation($this, $sql);
            default:
            return new Adept_Db_MySql_Statement($this, $sql);
        }
    }
    
    /**
     * Escape special chars for DB security
     * @param string $value
     * @return string
     */
    public function escape($value) 
    {
        return mysql_real_escape_string($value);    
    } 
    
    public function getTableInfo($tableName)
    {
        return new Adept_Db_MySql_TableInfo($tableName, $this);
    }
    
    public function getSelectQuery() 
    {
        return new Adept_Db_Query_Select($this);
    }    
    
    public function getInsertQuery() 
    {
        return new Adept_Db_Query_Insert($this);
    }    
    
    public function getUpdateQuery() 
    {
        return new Adept_Db_Query_Update($this);
    }    
    
    public function getDeleteQuery() 
    {
        return new Adept_Db_Query_Delete($this);
    }    

}